﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FluentValidation;
using FluentValidation.Results;

using RevClinic.Core.Resources;
using NHibernate;
using RevClinic.Core.Services;
using RevClinic.Core.Commands.Models;

namespace RevClinic.Core.Commands.ModelValidators
{
    public class UserCreateModelValidator :
        AbstractValidator<UserCreateModel>
    {
        public IUserService _userService;

        public readonly int MinLoginLength = 5;
        public readonly int MaxLoginLength = 20;
        public readonly int MinPasswordLength = 6;
        public readonly int MaxPasswordLength = 20;
        public readonly string LoginRequiredCharsRegex = @"[\w]+";
        public readonly string PasswordRequireCharsRegex = @"[^\s]+";

        public UserCreateModelValidator(IUserService userService)
        {
            _userService = userService;
            InitRules();
        }

        private void InitRules()
        {
            FirstNameRules();
            SurnameRules();
            LoginRules();
            PasswordRules();
            RepeatedPasswordRules();
        }

        private void LoginRules()
        {
            RuleFor(m => m.Login)
                .NotEmpty()
                .WithMessage(ModelValidationMsg.Login_IsEmpty);

            RuleFor(m => m.Login)
                .Length(MinLoginLength, MaxLoginLength)
                .WithMessage(ModelValidationMsg.Login_HasIncorrectLength);

            RuleFor(m => m.Login)
                .Matches(LoginRequiredCharsRegex)
                .WithMessage(ModelValidationMsg.Login_HasIncorrectChars);

            RuleFor(m => m.Login)
                .Must(login => _userService.IsUserLoginOccupied(login) == false)
                .WithMessage(ModelValidationMsg.Login_AlreadyUsed);
        }

        private void PasswordRules()
        {
            RuleFor(m => m.Password)
                .NotEmpty()
                .WithMessage(ModelValidationMsg.Password_IsEmpty);

            RuleFor(m => m.Password)
                .Length(MinPasswordLength, MaxPasswordLength)
                .WithMessage(ModelValidationMsg.Password_HasIncorrectLength);

            RuleFor(m => m.Password)
                .Matches(PasswordRequireCharsRegex)
                .WithMessage(ModelValidationMsg.Password_HasIncorrectChars);
        }

        private void RepeatedPasswordRules()
        {
            RuleFor(m => m.RepeatedPassword)
                .Must((model, repeatedPassword) => {
                    return model.Password == repeatedPassword;
                })
                .WithMessage(ModelValidationMsg.RepeatedPassword_IsIncompatible);
        }

        private void FirstNameRules()
        {
            RuleFor(m => m.FirstName)
                .NotEmpty()
                .WithMessage(ModelValidationMsg.DoctorCreate_FirstName_IsEmpty);
        }

        private void SurnameRules()
        {
            RuleFor(m => m.Surname)
                .NotEmpty()
                .WithMessage(ModelValidationMsg.DoctorCreate_Surname_IsEmpty);
        }
    }
}
